<!DOCTYPE html>

<html>
    
    <head>
        
        <meta charset=UTF-8 />
        <title>HTML5 Canvas と JavaScript を使って作る追尾サンプル</title>
        
        <!-- util系 -->
        <script>
            var $id = function(id) { return document.getElementById(id); }
        </script>
        
        <!-- application系 -->
        <script>
            
            // 定数
            var FPS             = 60;
            var SCREEN_WIDTH    = 640;
            var SCREEN_HEIGHT   = 480;
            var CIRCLE_RADIUS   = 30;
            var CIRCLE_MAX_NUM  = 10;
            var CIRCLE_PURSUIT_RATE = 0.1;  // 収束率
            
            // グローバル
            var global = {};
            global.context      = null;
            global.circleList   = [];
            global.mouseX       = null;
            global.mouseY       = null;
            
            window.onload = function()
            {
                init();
                run();
            };
            
            var init = function()
            {
                var canvas = $id("c");
                global.context = canvas.getContext("2d");
                
                // Circle を生成
                for (var i=0; i<CIRCLE_MAX_NUM; ++i)
                {
                    global.circleList.push(new Circle(
                        Math.random() * SCREEN_WIDTH,
                        Math.random() * SCREEN_HEIGHT,
                        "hsla(" + (360/CIRCLE_MAX_NUM)*i +  ", 75%, 50%, 0.75)"
                    ));
                }
                // 1個前に生成された Circle を Target としてセット
                for (var i=1,len=global.circleList.length; i<len; ++i)
                {
                    global.circleList[i].target = global.circleList[i-1];
                }
                
                // Canvas にマウスイベントを登録
                canvas.addEventListener("mousemove", updateMousePos, false); // マウス移動時イベント
                canvas.addEventListener("mouseout", resetMousePos, false); // マウスが画面外に出た際のイベント
            };
            
            var run = function()
            {
                var _run = function()
                {
                    update();
                    draw();
                    
                    setTimeout(_run, 1000.0/FPS);
                };
                
                setTimeout(_run, 1000.0/FPS);
            };
            
            var update = function()
            {
                for (var i=0,len=global.circleList.length; i<len; ++i)
                {
                    global.circleList[i].update();
                }
            };
            
            var draw = function()
            {
                var ctx = global.context;
                ctx.fillStyle = "black";
                ctx.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
                
                // 円を描画
                ctx.save();
                ctx.globalCompositeOperation = "lighter";
                for (var i=0,len=global.circleList.length; i<len; ++i)
                {
                    global.circleList[i].draw(ctx);
                }
                ctx.restore();
            };
            
            
            /**
             * Circle クラス
             */
            var Circle = function(x, y, color)
            {
                this.x = x || 0;
                this.y = y || 0;
                this.color = color || "white";
                this.target= null;
            };
            
            Circle.prototype = {
                x: null,
                y: null,
                color: null,
                target: null,
                
                update: function()
                {
                    if (this.target) {
                        this.x += (this.target.x-this.x)*CIRCLE_PURSUIT_RATE;
                        this.y += (this.target.y-this.y)*CIRCLE_PURSUIT_RATE;
                    }
                    else if (global.mouseX && global.mouseY){
                        this.x += (global.mouseX-this.x)*CIRCLE_PURSUIT_RATE;
                        this.y += (global.mouseY-this.y)*CIRCLE_PURSUIT_RATE;
                    }
                },
                
                draw: function(ctx)
                {
                    ctx.fillStyle = this.color;
                    ctx.beginPath();
                    ctx.arc(this.x, this.y, CIRCLE_RADIUS, 0, Math.PI*2, false);
                    ctx.fill();
                    ctx.closePath();
                }
            };
            
            var updateMousePos = function(e)
            {
                var rect = e.target.getBoundingClientRect();
                global.mouseX = e.clientX - rect.left;
                global.mouseY = e.clientY - rect.top;
            };
            
            var resetMousePos = function()
            {
                global.mouseX = null;
                global.mouseY = null;
            };
            
            
        </script>
        
    </head>
    <body>
        <header>
            <h1>HTML5 Canvas と JavaScript を使って作る追尾サンプル</h1>
            <p>
                マウスに追尾する処理を追加
            </p>
        </header>
        <canvas id="c" width="640" height="480"></canvas>
    </body>
    
</html>










